#include "HP_PackServer.h"

EnHandleResult HP_PackServer::OnPrepareListen(ITcpServer* pSender, SOCKET soListen)
{
	if (GetCallBack("OnPrepareListen"))
	{
		lua_pushinteger(L, soListen);
		lua_call(L, 2, 1);
		return GetResult();
	}
	return HR_OK;
}

EnHandleResult HP_PackServer::OnAccept(ITcpServer* pSender, CONNID dwConnID, UINT_PTR soSvrent)
{
	if (GetCallBack("OnAccept"))
	{
		lua_pushinteger(L, dwConnID);
		lua_pushinteger(L, soSvrent);
		lua_call(L, 3, 1);
		return GetResult();
	}
	return HR_OK;
}

EnHandleResult HP_PackServer::OnReceive(ITcpServer* pSender, CONNID dwConnID, const BYTE* pData, int iLength)
{
	if (GetCallBack("OnReceive"))
	{
		lua_pushinteger(L, dwConnID);
		lua_pushlstring(L, (const char*)pData, iLength);
		lua_call(L, 3, 1);
		return GetResult();
	}
	return HR_OK;
}

EnHandleResult HP_PackServer::OnSend(ITcpServer* pSender, CONNID dwConnID, const BYTE* pData, int iLength)
{
	if (GetCallBack("OnSend"))
	{
		lua_pushinteger(L, dwConnID);
		//lua_pushlightuserdata(L,(void*)pData);
		lua_pushinteger(L, iLength);
		lua_call(L, 3, 1);
		return GetResult();
	}
	return HR_OK;
}

EnHandleResult HP_PackServer::OnShutdown(ITcpServer* pSender)
{
	if (GetCallBack("OnShutdown"))
	{
		lua_call(L, 1, 1);
		return GetResult();
	}
	return HR_OK;
}

EnHandleResult HP_PackServer::OnClose(ITcpServer* pSender, CONNID dwConnID, EnSocketOperation enOperation, int iErrorCode)
{
	if (GetCallBack("OnClose"))
	{
		lua_pushinteger(L, dwConnID);
		switch (enOperation) {
			CASE(SO_UNKNOWN)
			CASE(SO_ACCEPT)
			CASE(SO_CONNECT)
			CASE(SO_SEND)
			CASE(SO_RECEIVE)
			CASE(SO_CLOSE)
		}
		lua_pushinteger(L, iErrorCode);
		lua_call(L, 4, 1);
		return GetResult();
	}
	return HR_OK;
}

static BOOL luaL_optboolean (lua_State *L, int arg,BOOL def) {
	if (lua_isnoneornil(L, arg)) {
		return def;
	}
	return lua_toboolean(L,arg);
}
static ITcpPackServer* GetServer(lua_State* L){
	HP_PackServer* p = *(HP_PackServer**)luaL_checkudata(L,1,"HP_PackServer");
	return p->m_Server;
}
//IPackSocket
static int SetMaxPackSize(lua_State* L){
	ITcpPackServer* Svr = GetServer(L);
	Svr->SetMaxPackSize((DWORD)luaL_checkinteger(L,2));
	return 0;
}
static int SetPackHeaderFlag(lua_State* L){
	ITcpPackServer* Svr = GetServer(L);
	Svr->SetPackHeaderFlag((USHORT)luaL_checkinteger(L,2));
	return 0;
}
static int GetMaxPackSize(lua_State* L){
	ITcpPackServer* Svr = GetServer(L);
	lua_pushinteger(L,Svr->GetMaxPackSize());
	return 1;
}
static int GetPackHeaderFlag(lua_State* L){
	ITcpPackServer* Svr = GetServer(L);
	lua_pushinteger(L,Svr->GetPackHeaderFlag());
	return 1;
}
//ITcpServer
static int SendSmallFile(lua_State* L){
	ITcpPackServer* Svr = GetServer(L);
	lua_pushboolean(L,Svr->SendSmallFile(luaL_checkinteger(L,2),luaL_checkstring(L,3),
		(LPWSABUF)luaL_optlstring(L,4,nullptr,NULL),
		(LPWSABUF)luaL_optlstring(L,5,nullptr,NULL)));
	return 1;
}
static int SetAcceptSocketCount(lua_State* L){
	ITcpPackServer* Svr = GetServer(L);
	Svr->SetAcceptSocketCount((DWORD)luaL_checkinteger(L,2));
	return 0;
}
static int SetSocketBufferSize(lua_State* L){
	ITcpPackServer* Svr = GetServer(L);
	Svr->SetSocketBufferSize((DWORD)luaL_checkinteger(L,2));
	return 0;
}
static int SetSocketListenQueue(lua_State* L){
	ITcpPackServer* Svr = GetServer(L);
	Svr->SetSocketListenQueue((DWORD)luaL_checkinteger(L,2));
	return 0;
}
static int SetKeepAliveTime(lua_State* L){
	ITcpPackServer* Svr = GetServer(L);
	Svr->SetKeepAliveTime((DWORD)luaL_checkinteger(L,2));
	return 0;
}
static int SetKeepAliveInterval(lua_State* L){
	ITcpPackServer* Svr = GetServer(L);
	Svr->SetKeepAliveInterval((DWORD)luaL_checkinteger(L,2));
	return 0;
}
static int GetAcceptSocketCount(lua_State* L){
	ITcpPackServer* Svr = GetServer(L);
	lua_pushinteger(L,Svr->GetAcceptSocketCount());
	return 1;
}
static int GetSocketBufferSize(lua_State* L){
	ITcpPackServer* Svr = GetServer(L);
	lua_pushinteger(L,Svr->GetSocketBufferSize());
	return 1;
}
static int GetSocketListenQueue(lua_State* L){
	ITcpPackServer* Svr = GetServer(L);
	lua_pushinteger(L,Svr->GetSocketListenQueue());
	return 1;
}
static int GetKeepAliveTime(lua_State* L){
	ITcpPackServer* Svr = GetServer(L);
	lua_pushinteger(L,Svr->GetKeepAliveTime());
	return 1;
}
static int GetKeepAliveInterval(lua_State* L){
	ITcpPackServer* Svr = GetServer(L);
	lua_pushinteger(L,Svr->GetKeepAliveInterval());
	return 1;
}
//IServer
static int Start(lua_State* L){
	ITcpPackServer* Svr = GetServer(L);
	BOOL r = Svr->Start(luaL_checkstring(L,2),(USHORT)luaL_checkinteger(L,3));
	lua_pushboolean(L,r);
	return 1;
}
static int GetListenAddress(lua_State* L){
	ITcpPackServer* Svr = GetServer(L);
	luaL_Buffer b;
	char* p = luaL_buffinitsize(L,&b,LUAL_BUFFERSIZE);
	int len = LUAL_BUFFERSIZE;
	USHORT port;
	if (Svr->GetListenAddress(p,len,port)){
		luaL_pushresultsize(&b,len-1);
		lua_pushinteger(L,port);
		return 2;
	}
	return 0;
}
//IComplexSocket
static int Stop(lua_State* L){
	ITcpPackServer* Svr = GetServer(L);
	HP_mutex*mutex = *(HP_mutex **)lua_getextraspace(L);
	HP_UnlockMutex(mutex);
	BOOL r = Svr->Stop();
	HP_LockMutex(mutex);
	lua_pushboolean(L,r);
	return 1;
}

static int Send(lua_State* L){
	ITcpPackServer* Svr = GetServer(L);
	size_t len;
	BYTE* buf = (BYTE*)luaL_checklstring(L,3,&len);
	lua_pushboolean(L,Svr->Send((CONNID)luaL_checkinteger(L,2),buf,(int)len,(int)luaL_optinteger(L,4,0)));
	return 1;
}
//static int SendPackets(lua_State* L){
//	ITcpPackServer* Svr = GetServer(L);
//
//	return 0;
//}
static int PauseReceive(lua_State* L){
	ITcpPackServer* Svr = GetServer(L);
	lua_pushboolean(L,Svr->PauseReceive(luaL_checkinteger(L,2),luaL_optboolean(L,3,TRUE)));
	return 1;
}

static int Disconnect(lua_State* L){
	ITcpPackServer* Svr = GetServer(L);
	lua_pushboolean(L,Svr->Disconnect(luaL_checkinteger(L,2),luaL_optboolean(L,3,TRUE)));
	return 1;
}

static int DisconnectLongConnections(lua_State* L){
	ITcpPackServer* Svr = GetServer(L);
	lua_pushboolean(L,Svr->DisconnectLongConnections((DWORD)luaL_checkinteger(L,2),luaL_optboolean(L,3,TRUE)));
	return 1;
}

static int DisconnectSilenceConnections(lua_State* L){
	ITcpPackServer* Svr = GetServer(L);
	lua_pushboolean(L,Svr->DisconnectSilenceConnections((DWORD)luaL_checkinteger(L,2),luaL_optboolean(L,3,TRUE)));
	return 1;
}

static int Wait(lua_State* L){
	ITcpPackServer* Svr = GetServer(L);
	lua_pushboolean(L,Svr->Wait((DWORD)luaL_optinteger(L,2,INFINITE)));
	return 1;
}
//static int SetConnectionExtra(lua_State* L){
//	ITcpPackServer* Svr = GetServer(L);
//
//	return 0;
//}
//static int GetConnectionExtra(lua_State* L){
//	ITcpPackServer* Svr = GetServer(L);
//
//	return 0;
//}
static int IsSecure(lua_State* L){
	ITcpPackServer* Svr = GetServer(L);
	lua_pushboolean(L,Svr->IsSecure());
	return 1;
}
static int HasStarted(lua_State* L){
	ITcpPackServer* Svr = GetServer(L);
	lua_pushboolean(L,Svr->HasStarted());
	return 1;
}
static int GetState(lua_State* L){
	ITcpPackServer* Svr = GetServer(L);
	switch (Svr->GetState()) {
		CASE(SS_STARTING)
		CASE(SS_STARTED)
		CASE(SS_STOPPING)
		CASE(SS_STOPPED)
	}
	return 1;
}
static int GetConnectionCount(lua_State* L){
	ITcpPackServer* Svr = GetServer(L);
	lua_pushinteger(L,Svr->GetConnectionCount());
	return 1;
}
static int GetAllConnectionIDs(lua_State* L){
	ITcpPackServer* Svr = GetServer(L);
	DWORD num = Svr->GetConnectionCount();
	CONNID *id = new CONNID[num];
	lua_createtable(L,num,0);
	if (Svr->GetAllConnectionIDs(id,num)){
		for (DWORD i=0;i<num;i++){
			lua_pushinteger(L,id[i]);
			lua_seti(L,-2,i+1);
		}
	}
	delete []id;
	return 1;
}
static int GetConnectPeriod(lua_State* L){
	ITcpPackServer* Svr = GetServer(L);
	DWORD v;
	Svr->GetConnectPeriod(luaL_checkinteger(L,2),v);
	lua_pushinteger(L,v);
	return 1;
}
static int GetSilencePeriod(lua_State* L){
	ITcpPackServer* Svr = GetServer(L);
	DWORD v;
	Svr->GetSilencePeriod(luaL_checkinteger(L,2),v);
	lua_pushinteger(L,v);
	return 1;
}
static int GetLocalAddress(lua_State* L){
	ITcpPackServer* Svr = GetServer(L);
	luaL_Buffer b;
	char* p = luaL_buffinitsize(L,&b,LUAL_BUFFERSIZE);
	int len = LUAL_BUFFERSIZE;
	USHORT port;
	if (Svr->GetLocalAddress(luaL_checkinteger(L,2),p,len,port)){
		luaL_pushresultsize(&b,len-1);
		lua_pushinteger(L,port);
		return 2;
	}
	return 0;
}
static int GetRemoteAddress(lua_State* L){
	ITcpPackServer* Svr = GetServer(L);
	luaL_Buffer b;
	char* p = luaL_buffinitsize(L,&b,LUAL_BUFFERSIZE);
	int len = LUAL_BUFFERSIZE;
	USHORT port;
	if (Svr->GetRemoteAddress(luaL_checkinteger(L,2),p,len,port)){
		luaL_pushresultsize(&b,len-1);
		lua_pushinteger(L,port);
		return 2;
	}
	return 0;
}
static int GetLastError(lua_State* L){
	ITcpPackServer* Svr = GetServer(L);
	switch (Svr->GetLastError()) {
		CASE(SE_OK)
		CASE(SE_ILLEGAL_STATE)
		CASE(SE_INVALID_PARAM)
		CASE(SE_SOCKET_CREATE)
		CASE(SE_SOCKET_BIND)
		CASE(SE_SOCKET_PREPARE)
		CASE(SE_SOCKET_LISTEN)
		CASE(SE_CP_CREATE)
		CASE(SE_WORKER_THREAD_CREATE)
		CASE(SE_DETECT_THREAD_CREATE)
		CASE(SE_SOCKE_ATTACH_TO_CP)
		CASE(SE_CONNECT_SERVER)
		CASE(SE_NETWORK)
		CASE(SE_DATA_PROC)
		CASE(SE_DATA_SEND)
		CASE(SE_SSL_ENV_NOT_READY)
	}
	return 1;
}
static int GetLastErrorDesc(lua_State* L){
	ITcpPackServer* Svr = GetServer(L);
	lua_pushstring(L,Svr->GetLastErrorDesc());
	return 1;
}
static int GetPendingDataLength(lua_State* L){
	ITcpPackServer* Svr = GetServer(L);
	int v;
	Svr->GetPendingDataLength(luaL_checkinteger(L,2),v);
	lua_pushinteger(L,v);
	return 1;
}
static int IsPauseReceive(lua_State* L){
	ITcpPackServer* Svr = GetServer(L);
	BOOL v;
	Svr->GetPendingDataLength(luaL_checkinteger(L,2),v);
	lua_pushboolean(L,v);
	return 1;
}
static int IsConnected(lua_State* L){
	ITcpPackServer* Svr = GetServer(L);
	lua_pushboolean(L,Svr->IsConnected(luaL_checkinteger(L,2)));
	return 1;
}
static int SetReuseAddressPolicy(lua_State* L){
	ITcpPackServer* Svr = GetServer(L);
	static const char *const opts[] = {"RAP_NONE", "RAP_ADDR_ONLY", "RAP_ADDR_AND_PORT", NULL};
	Svr->SetReuseAddressPolicy(EnReuseAddressPolicy(luaL_checkoption(L, 2, "RAP_NONE", opts)));
	return 0;
}
static int SetSendPolicy(lua_State* L){
	ITcpPackServer* Svr = GetServer(L);
	static const char *const opts[] = {"SP_PACK", "SP_SAFE", "SP_DIRECT", NULL};
	Svr->SetSendPolicy(EnSendPolicy(luaL_checkoption(L, 2, "SP_PACK", opts)));
	return 0;
}
static int SetOnSendSyncPolicy(lua_State* L){
	ITcpPackServer* Svr = GetServer(L);
	static const char *const opts[] = {"OSSP_NONE", "OSSP_CLOSE", "OSSP_RECEIVE", NULL};
	Svr->SetOnSendSyncPolicy(EnOnSendSyncPolicy(luaL_checkoption(L, 2, "OSSP_NONE", opts)));
	return 0;
}
static int SetMaxConnectionCount(lua_State* L){
	ITcpPackServer* Svr = GetServer(L);
	Svr->SetMaxConnectionCount((DWORD)luaL_checkinteger(L,2));
	return 0;
}
static int SetFreeSocketObjLockTime(lua_State* L){
	ITcpPackServer* Svr = GetServer(L);
	Svr->SetFreeSocketObjLockTime((DWORD)luaL_checkinteger(L,2));
	return 0;
}
static int SetFreeSocketObjPool(lua_State* L){
	ITcpPackServer* Svr = GetServer(L);
	Svr->SetFreeSocketObjPool((DWORD)luaL_checkinteger(L,2));
	return 0;
}
static int SetFreeBufferObjPool(lua_State* L){
	ITcpPackServer* Svr = GetServer(L);
	Svr->SetFreeBufferObjPool((DWORD)luaL_checkinteger(L,2));
	return 0;
}
static int SetFreeSocketObjHold(lua_State* L){
	ITcpPackServer* Svr = GetServer(L);
	Svr->SetFreeSocketObjHold((DWORD)luaL_checkinteger(L,2));
	return 0;
}
static int SetFreeBufferObjHold(lua_State* L){
	ITcpPackServer* Svr = GetServer(L);
	Svr->SetFreeBufferObjHold((DWORD)luaL_checkinteger(L,2));
	return 0;
}
static int SetWorkerThreadCount(lua_State* L){
	ITcpPackServer* Svr = GetServer(L);
	Svr->SetWorkerThreadCount((DWORD)luaL_checkinteger(L,2));
	return 0;
}
static int SetMarkSilence(lua_State* L){
	ITcpPackServer* Svr = GetServer(L);
	Svr->SetMarkSilence(lua_toboolean(L,2));
	return 0;
}
static int GetReuseAddressPolicy(lua_State* L){
	ITcpPackServer* Svr = GetServer(L);
	switch (Svr->GetReuseAddressPolicy()) {
		CASE(RAP_NONE)
		CASE(RAP_ADDR_ONLY)
		CASE(RAP_ADDR_AND_PORT)
	}
	return 1;
}
static int GetSendPolicy(lua_State* L){
	ITcpPackServer* Svr = GetServer(L);
	switch (Svr->GetSendPolicy()) {
		CASE(SP_PACK)
		CASE(SP_SAFE)
		CASE(SP_DIRECT)
	}
	return 1;
}
static int GetOnSendSyncPolicy(lua_State* L){
	ITcpPackServer* Svr = GetServer(L);
	switch (Svr->GetOnSendSyncPolicy()) {
		CASE(OSSP_NONE)
		CASE(OSSP_CLOSE)
		CASE(OSSP_RECEIVE)
	}
	return 1;
}
static int GetMaxConnectionCount(lua_State* L){
	ITcpPackServer* Svr = GetServer(L);
	lua_pushinteger(L,Svr->GetMaxConnectionCount());
	return 1;
}
static int GetFreeSocketObjLockTime(lua_State* L){
	ITcpPackServer* Svr = GetServer(L);
	lua_pushinteger(L,Svr->GetFreeSocketObjLockTime());
	return 1;
}
static int GetFreeSocketObjPool(lua_State* L){
	ITcpPackServer* Svr = GetServer(L);
	lua_pushinteger(L,Svr->GetFreeSocketObjPool());
	return 1;
}
static int GetFreeBufferObjPool(lua_State* L){
	ITcpPackServer* Svr = GetServer(L);
	lua_pushinteger(L,Svr->GetFreeBufferObjPool());
	return 1;
}
static int GetFreeSocketObjHold(lua_State* L){
	ITcpPackServer* Svr = GetServer(L);
	lua_pushinteger(L,Svr->GetFreeSocketObjHold());
	return 1;
}
static int GetFreeBufferObjHold(lua_State* L){
	ITcpPackServer* Svr = GetServer(L);
	lua_pushinteger(L,Svr->GetFreeBufferObjHold());
	return 1;
}
static int GetWorkerThreadCount(lua_State* L){
	ITcpPackServer* Svr = GetServer(L);
	lua_pushinteger(L,Svr->GetWorkerThreadCount());
	return 1;
}
static int IsMarkSilence(lua_State* L){
	ITcpPackServer* Svr = GetServer(L);
	lua_pushboolean(L,Svr->IsMarkSilence());
	return 1;
}

static int Creat_HP_PackServer(lua_State* L){
	HP_PackServer* p = new HP_PackServer(L);
	HP_PackServer** ud = (HP_PackServer**)lua_newuserdata(L,sizeof(HP_PackServer*));
	*ud = p;
	luaL_setmetatable(L,"HP_PackServer");
	return 1;
}

static int Destroy_HP_PackServer(lua_State* L){
	HP_PackServer* ud = *(HP_PackServer**)luaL_checkudata(L,1,"HP_PackServer");
	Stop(L);
	delete ud;
	return 0;
}

#if defined(LUA_BUILD_AS_DLL)
extern "C" LUAMOD_API
#else
LUAMOD_API
#endif
	int luaopen_ghpsocket_packserver(lua_State* L)
{
	luaL_Reg methods[] = {
		{"SetMaxPackSize",SetMaxPackSize},
		{"SetPackHeaderFlag",SetPackHeaderFlag},
		{"GetMaxPackSize",GetMaxPackSize},
		{"GetPackHeaderFlag",GetPackHeaderFlag},
		{"SendSmallFile",SendSmallFile},
		{"SetAcceptSocketCount",SetAcceptSocketCount},
		{"SetSocketBufferSize",SetSocketBufferSize},
		{"SetSocketListenQueue",SetSocketListenQueue},
		{"SetKeepAliveTime",SetKeepAliveTime},
		{"SetKeepAliveInterval",SetKeepAliveInterval},
		{"GetAcceptSocketCount",GetAcceptSocketCount},
		{"GetSocketBufferSize",GetSocketBufferSize},
		{"GetSocketListenQueue",GetSocketListenQueue},
		{"GetKeepAliveTime",GetKeepAliveTime},
		{"GetKeepAliveInterval",GetKeepAliveInterval},
		{"Start",Start},
		{"GetListenAddress",GetListenAddress},
		{"Stop",Stop},
		{"Send",Send},
		//{"SendPackets",SendPackets},
		{"PauseReceive",PauseReceive},
		{"Disconnect",Disconnect},
		{"DisconnectLongConnections",DisconnectLongConnections},
		{"DisconnectSilenceConnections",DisconnectSilenceConnections},
		{"Wait",Wait},
		//{"SetConnectionExtra",SetConnectionExtra},
		//{"GetConnectionExtra",GetConnectionExtra},
		{"IsSecure",IsSecure},
		{"HasStarted",HasStarted},
		{"GetState",GetState},
		{"GetConnectionCount",GetConnectionCount},
		{"GetAllConnectionIDs",GetAllConnectionIDs},
		{"GetConnectPeriod",GetConnectPeriod},
		{"GetSilencePeriod",GetSilencePeriod},
		{"GetLocalAddress",GetLocalAddress},
		{"GetRemoteAddress",GetRemoteAddress},
		{"GetLastError",GetLastError},
		{"GetLastErrorDesc",GetLastErrorDesc},
		{"GetPendingDataLength",GetPendingDataLength},
		{"IsPauseReceive",IsPauseReceive},
		{"IsConnected",IsConnected},
		{"SetReuseAddressPolicy",SetReuseAddressPolicy},
		{"SetSendPolicy",SetSendPolicy},
		{"SetOnSendSyncPolicy",SetOnSendSyncPolicy},
		{"SetMaxConnectionCount",SetMaxConnectionCount},
		{"SetFreeSocketObjLockTime",SetFreeSocketObjLockTime},
		{"SetFreeSocketObjPool",SetFreeSocketObjPool},
		{"SetFreeBufferObjPool",SetFreeBufferObjPool},
		{"SetFreeSocketObjHold",SetFreeSocketObjHold},
		{"SetFreeBufferObjHold",SetFreeBufferObjHold},
		{"SetWorkerThreadCount",SetWorkerThreadCount},
		{"SetMarkSilence",SetMarkSilence},
		{"GetReuseAddressPolicy",GetReuseAddressPolicy},
		{"GetSendPolicy",GetSendPolicy},
		{"GetOnSendSyncPolicy",GetOnSendSyncPolicy},
		{"GetMaxConnectionCount",GetMaxConnectionCount},
		{"GetFreeSocketObjLockTime",GetFreeSocketObjLockTime},
		{"GetFreeSocketObjPool",GetFreeSocketObjPool},
		{"GetFreeBufferObjPool",GetFreeBufferObjPool},
		{"GetFreeSocketObjHold",GetFreeSocketObjHold},
		{"GetFreeBufferObjHold",GetFreeBufferObjHold},
		{"GetWorkerThreadCount",GetWorkerThreadCount},
		{"IsMarkSilence",IsMarkSilence},
		{NULL, NULL},
	};
	luaL_newmetatable(L, "HP_PackServer");
	luaL_newlib(L, methods);
	lua_setfield(L, -2, "__index");
	lua_pushcfunction (L, Destroy_HP_PackServer);
	lua_setfield (L, -2, "__gc");
	lua_pop(L,1);

	lua_pushcfunction(L,Creat_HP_PackServer);
	return 1;
}